/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_comm.c                                         */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/09 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdarg.h>

#include "frmem.h"
#include "frlog.h"
#include "frsutl.h"

#include "ora_util.h"
#include "ora_comm.h"
#include "../ttc/ora_ttc_proto.h"

static char hex_asc[] = "0123456789abcdef";
#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]

int ora_get_jdbc_type(int i_internal_type)
{
    int i_jdbc_type = 0;
    switch (i_internal_type) {
        case ORA_DTY_VARCHAR:
            i_jdbc_type = ORA_JDBCTYPE_VARCHAR;
            break;
        case ORA_DTY_VARNUM:
            i_jdbc_type = ORA_JDBCTYPE_NUMERIC;
            break;
        case ORA_DTY_LONG:
            i_jdbc_type = ORA_JDBCTYPE_LONGVARCHAR;
            break;
        case ORA_DTY_DATE:
            i_jdbc_type = ORA_JDBCTYPE_DATE;
            break;
        case ORA_DTY_RAW:
            i_jdbc_type = ORA_JDBCTYPE_RAW;
            break;
        case ORA_DTY_LONG_RAW:
            i_jdbc_type = ORA_JDBCTYPE_LONGVARBINARY;
            break;
        case ORA_DTY_CHAR:
            i_jdbc_type = ORA_JDBCTYPE_CHAR;
            break;
        case ORA_DTY_BINARY_FLOAT:
            i_jdbc_type = ORA_JDBCTYPE_BINARY_FLOAT;
            break;
        case ORA_DTY_BINARY_DOUBLE:
            i_jdbc_type = ORA_JDBCTYPE_BINARY_DOUBLE;
            break;
        case ORA_DTY_RESULT_SET:
            i_jdbc_type = ORA_JDBCTYPE_CURSOR;
            break;
        case ORA_DTY_ROWID:
            i_jdbc_type = ORA_JDBCTYPE_ROWID;
            break;
        case ORA_DTY_NAMED_TYPE:
            i_jdbc_type = ORA_JDBCTYPE_STRUCT;
            break;
        case ORA_DTY_REF_TYPE:
            i_jdbc_type = ORA_JDBCTYPE_REF;
            break;
        case ORA_DTY_CLOB:
            i_jdbc_type = ORA_JDBCTYPE_CLOB;
            break;
        case ORA_DTY_BLOB:
            i_jdbc_type = ORA_JDBCTYPE_BLOB;
            break;
        case ORA_DTY_BFILE:
            i_jdbc_type = ORA_JDBCTYPE_BFILE;
            break;
        case ORA_DTY_TIMESTAMP:
            i_jdbc_type = ORA_JDBCTYPE_TIMESTAMP;
            break;
        case ORA_DTY_TIMESTAMPTZ:
            i_jdbc_type = ORA_JDBCTYPE_TIMESTAMPTZ;
            break;
        case ORA_DTY_INTERVALYM:
            i_jdbc_type = ORA_JDBCTYPE_INTERVALYM;
            break;
        case ORA_DTY_INTERVALDS:
            i_jdbc_type = ORA_JDBCTYPE_INTERVALDS;
            break;
        case ORA_DTY_TIMESTAMPLTZ:
            i_jdbc_type = ORA_JDBCTYPE_TIMESTAMPLTZ;
            break;
        case ORA_DTY_NULL_TYPE:
            i_jdbc_type = ORA_JDBCTYPE_NULL;
            break;
        case ORA_DTY_PLSQL_INDEX_TABLE:
            i_jdbc_type = ORA_JDBCTYPE_PLSQL_INDEX_TABLE;
            break;
        case ORA_DTY_FIXED_CHAR:
            i_jdbc_type = ORA_JDBCTYPE_FIXED_CHAR;
            break;
        default:
            i_jdbc_type = i_internal_type;
    }
    return i_jdbc_type;
}

/*******************************************************************************
*  FUNC     :  按一个字节打印十六进行字符串
*  ARGS     :  *p_inbuff                        (输入的buff)
*           :  i_inbuff_len                     (输入的buff长度)
*           :  p_outbuff                        (输出的buff)
*           :  i_outbuff_len                    (输出的buff长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_bin_to_hex_string(char *p_inbuff, int i_inbuff_len, char *p_outbuff, int i_outbuff_len)
{
    int i_loop;
    char c;
    int i_used = 0;
    int i_len = i_outbuff_len / 2 < i_inbuff_len ? i_outbuff_len / 2 : i_inbuff_len;

    if (i_outbuff_len % 2 != 0)
        return;

    for (i_loop = 0; i_loop < i_len; i_loop++)
    {
        c = p_inbuff[i_loop];
        p_outbuff[i_used++] = hex_asc_hi(c);
        p_outbuff[i_used++] = hex_asc_lo(c);
    }

    return;
}

/*******************************************************************************
*  FUNC     :  按一个字节打印十六进行字符串
*  ARGS     :  *p_buff  (char*字符串)
*           :  i_len   (字符串长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __print_hex_string(char *p_buff, int i_len)
{
    int i_loop;

    for (i_loop = 0; i_loop < i_len; i_loop++)
    {
        printf("%02x", p_buff[i_loop] & 0xFF);
    }

    return;
}

/*******************************************************************************
*  FUNC     :  打印指定位置的包内容
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*           :  i_pos                                (开始位置)
*           :  i_len                                (长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __ora_print_packet_specified(L7_ora_packet *p_st_ora_packet, int i_pos, int i_len)
{
    if (p_st_ora_packet == NULL)
        return;
    char *p_buff_tmp = NULL;
    if (bytebuff_show(p_st_ora_packet->p_st_packet, i_pos, i_len, &p_buff_tmp) != FR_SUCC)
        return;
    __print_hex_string(p_buff_tmp, i_len);
    ora_free((void **) &p_buff_tmp);
    return;
}

/*******************************************************************************
*  FUNC     :  打印当前位置开始的包内容
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __ora_print_packet_current(L7_ora_packet *p_st_ora_packet)
{
    if (p_st_ora_packet == NULL)
        return;
    char *p_buff_tmp = NULL;
    if (bytebuff_show(p_st_ora_packet->p_st_packet, bytebuff_getPosition(p_st_ora_packet->p_st_packet), bytebuff_remaining(p_st_ora_packet->p_st_packet), &p_buff_tmp) != FR_SUCC)
        return;
    __print_hex_string(p_buff_tmp, bytebuff_remaining(p_st_ora_packet->p_st_packet));
    ora_free((void **) &p_buff_tmp);
    return;
}

/*******************************************************************************
*  FUNC     :  打印整个包内容
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __ora_print_packet(L7_ora_packet *p_st_ora_packet)
{
    if (p_st_ora_packet == NULL)
        return;
    char *p_buff_tmp = NULL;
    if (bytebuff_show(p_st_ora_packet->p_st_packet, 0, bytebuff_length(p_st_ora_packet->p_st_packet), &p_buff_tmp) != FR_SUCC)
        return;
    __print_hex_string(p_buff_tmp, bytebuff_length(p_st_ora_packet->p_st_packet));
    ora_free((void **) &p_buff_tmp);
    return;
}

/*******************************************************************************
*  FUNC     :  十六进制字符串转成char*
*  ARGS     :  *p_src                              (数据内容)
*           :  i_len                               (数据长度)
*  RTN      :  char*
*  NOTE     :
*******************************************************************************/
char* hex_string_to_char_array(const char *p_src, int i_len)
{
    char *p_buffer = NULL;;
    if ((p_buffer = (char *) frmalloc(i_len * sizeof(char))) == NULL)
    {
        ORA_MALLOCK_ERR;
        return NULL;
    }

    char *dst = p_buffer;
    char *end = p_buffer + i_len;
    unsigned int u;

    while (dst < end && sscanf(p_src, "%2x", &u) == 1)
    {
        *dst++ = u;
        p_src += 2;
    }

    return p_buffer;
}

/*******************************************************************************
*  FUNC     :  时间格式化成 2015-03-29 22:25:12.448671 的格式
*  ARGS     :  *p_tv                           (时间戳)
*           :  *p_time                         (buffer)
*           :  ui_time_size                    (buffer size)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ora_frtime2datetimestr(struct timeval *p_tv
                                        , char *p_time
                                        , unsigned int ui_time_size)
{
    struct tm *p_tm = NULL;

    if(p_tv == NULL || p_time == NULL || ui_time_size <= 1)
        return FR_FAIL;

    p_tm = localtime(&(p_tv->tv_sec));

    snprintf(p_time,ui_time_size,"%04d-%02d-%02d %02d:%02d:%02d.%06ld",
             p_tm->tm_year + 1900,p_tm->tm_mon + 1,p_tm->tm_mday,
             p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec,p_tv->tv_usec);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  时间格式化成 22:25:12.448671 的格式
*  ARGS     :  *p_tv                           (时间戳)
*           :  *p_time                         (buffer)
*           :  ui_time_size                    (buffer size)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int ora_util_frtime2timestr(struct timeval *p_tv
                            , char *p_time
                            , unsigned int ui_time_size)
{
    struct tm *p_tm = NULL;

    if(p_tv == NULL || p_time == NULL || ui_time_size <= 1)
        return FR_FAIL;

    p_tm = localtime(&(p_tv->tv_sec));

    snprintf(p_time,ui_time_size,"%02d:%02d:%02d.%06ld",
             p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec,p_tv->tv_usec);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  打印时间
*  ARGS     :  st_timestamp                         (时间戳)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __ora_util_print_timeval(struct timeval st_timestamp)
{
    char arr_buff[64];
    __ora_frtime2datetimestr(&st_timestamp, arr_buff, sizeof(arr_buff));
    printf(":[%s]\n", arr_buff);
}

/*******************************************************************************
*  FUNC     :  打印L7session_oracle的信息
*  ARGS     :  *p_st_sess                         (L7session_oracle信息)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __ora_util_print_sess(L7session_ora *p_st_sess)
{
    int i_CTcap15;
    printf(KMAGENTA "\n*********************************\n");
    printf("*********************************\n");

    printf("* is use oci? [%s]\n", p_st_sess->i_use_oci == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_use_oci == FR_YES ? "true" : "false");
    printf("* is use special field? [%s]\n", p_st_sess->i_use_special_field == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_use_special_field == FR_YES ? "true" : "false");
    printf("* tns version send? [%d]\n", p_st_sess->s_tns_version_req);
    printf("* tns version? [%d]\n", p_st_sess->s_tns_version);
    printf("* accept negotiated options? [0x%04x]\n", p_st_sess->s_negotiated_options);
    printf("* ttc version? [%d]\n", p_st_sess->c_ttc_version);
    printf("* cli is big endian [%s]?\n", p_st_sess->i_cli_is_bigendian == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_cli_is_bigendian == FR_YES ? "true" : "false");
    printf("* srv is big endian [%s]?\n", p_st_sess->i_srv_is_bigendian == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_srv_is_bigendian == FR_YES ? "true" : "false");
    printf("* version number? [%d]\n", p_st_sess->s_version_number);
    printf("* p_srv_compile_time_capabilities:[");
    for (int i = 0; i < p_st_sess->s_srv_compile_time_capabilities_len; i++)
    {
        printf("%d", p_st_sess->p_srv_compile_time_capabilities[i]);
        if (i != p_st_sess->s_srv_compile_time_capabilities_len - 1)
            printf(" ");
    }
    printf("]\n");
    printf("* p_CTcap:[");
    for (int i = 0; i < p_st_sess->s_CTcap_len; i++)
    {
        printf("%d", p_st_sess->p_CTcap[i]);
        if (i != p_st_sess->s_CTcap_len - 1)
            printf(" ");
    }
    printf("]\n");
    printf("* p_RTcap:[");
    for (int i = 0; i < p_st_sess->s_RTcap_len; i++)
    {
        printf("%d", p_st_sess->p_RTcap[i]);
        if (i != p_st_sess->s_RTcap_len - 1)
            printf(" ");
    }
    printf("]\n");
//    printf("* p_CTcap[4]? [%d]\n", p_st_sess->s_CTcap_len >= 5 ? p_st_sess->p_CTcap[4] : 0);
    printf("* oracle version? [%d]\n", p_st_sess->s_ora_version);
    printf("* pro srv version? [%d]\n", p_st_sess->c_pro_srv_version);
    printf("* cli charset in? [%d]\n", p_st_sess->s_cli_charset_in);
    printf("* cli charset out? [%d]\n", p_st_sess->s_cli_charset_out);
    printf("* srv charset? [%d]\n", p_st_sess->s_srv_charset);

    printf("* large sdu? [%s]\n", p_st_sess->i_is_large_sdu == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_is_large_sdu == FR_YES ? "true" : "false");
    printf("* i_useCLR_big_chunks? [%s]\n", p_st_sess->i_useCLR_big_chunks == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_useCLR_big_chunks == FR_YES ? "true" : "false");
    printf("* i_useLobPrefetch? [%s]\n", p_st_sess->i_useLobPrefetch == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_useLobPrefetch == FR_YES ? "true" : "false");
    printf("* pool enabled? [%s]\n", p_st_sess->i_pool_enabled == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_pool_enabled == FR_YES ? "true" : "false");
    printf("* session data unit size? [%d]\n", p_st_sess->s_sdu);

    printf("* client name? [%s]\n", p_st_sess->p_client_hostname == NULL ? "" : p_st_sess->p_client_hostname);
    printf("* program? [%s]\n", p_st_sess->p_program == NULL ? "" : p_st_sess->p_program);
    printf("* db sid? [%s]\n", p_st_sess->p_db_sid == NULL ? "" : p_st_sess->p_db_sid);
    printf("* ttc type rep? [%d][%d][%d][%d][%d]\n", p_st_sess->arr_ttc_type_rep[0],
            p_st_sess->arr_ttc_type_rep[1],
            p_st_sess->arr_ttc_type_rep[2],
            p_st_sess->arr_ttc_type_rep[3],
            p_st_sess->arr_ttc_type_rep[4]);
    printf("* c_conversion_flags? [%d]\n", p_st_sess->c_conversion_flags);
    printf("* i_c2snlsratio? [%d]\n", p_st_sess->i_c2snlsratio);
    if (p_st_sess->i_use_special_field == FR_YES)
    {
        printf("* i_oci_stmt_req_skip4_ttc7? [%s]\n", p_st_sess->i_oci_stmt_req_skip4_ttc7 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_oci_stmt_req_skip4_ttc7 == FR_YES ? "true" : "false");
        printf("* i_oci_stmt_req_skip4_ttc8? [%s]\n", p_st_sess->i_oci_stmt_req_skip4_ttc8 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_oci_stmt_req_skip4_ttc8 == FR_YES ? "true" : "false");
        printf("* i_oci_oversion_skip4? [%s]\n", p_st_sess->i_oci_oversion_skip4 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_oci_oversion_skip4 == FR_YES ? "true" : "false");
    }
    if (p_st_sess->i_use_oci == FR_YES)
        printf("* i_ptr_len? [%d]\n", p_st_sess->i_ptr_len);
    i_CTcap15 = ora_has_svr_compile_time_capability(p_st_sess, 15, 1);
    printf("* compile_time_capability[15] == 1? [%s]\n", i_CTcap15 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : i_CTcap15 == FR_YES ? "true" : "false");
    printf("* i_send_typerep? [%s]\n", p_st_sess->i_send_typerep == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : (p_st_sess->i_send_typerep ? "true" : "false"));
    printf("* i_closed_count? [%d]\n", p_st_sess->i_closed_count);



    printf("\n* i_CHR_conversion_flags?            [%s]\n", p_st_sess->i_CHR_conversion_flags            == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_CHR_conversion_flags            == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_req_i?                 [%s]\n", p_st_sess->i_ttc8_stmt_req_i                 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_req_i                 == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_req_j?                 [%s]\n", p_st_sess->i_ttc8_stmt_req_j                 == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_req_j                 == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_req_dml?               [%s]\n", p_st_sess->i_ttc8_stmt_req_dml               == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_req_dml               == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_req_oci_after_dml?     [%s]\n", p_st_sess->i_ttc8_stmt_req_oci_after_dml     == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_req_oci_after_dml     == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_dcb_recv?         [%s]\n", p_st_sess->i_ttc8_stmt_resp_dcb_recv         == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_dcb_recv         == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oac_skip1?        [%s]\n", p_st_sess->i_ttc8_stmt_resp_oac_skip1        == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oac_skip1        == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_udskpos?          [%s]\n", p_st_sess->i_ttc8_stmt_resp_udskpos          == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_udskpos          == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_udsflg?           [%s]\n", p_st_sess->i_ttc8_stmt_resp_udsflg           == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_udsflg           == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_dcbkm?            [%s]\n", p_st_sess->i_ttc8_stmt_resp_dcbkm            == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_dcbkm            == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_dcbni1?           [%s]\n", p_st_sess->i_ttc8_stmt_resp_dcbni1           == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_dcbni1           == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_dcbab2?           [%s]\n", p_st_sess->i_ttc8_stmt_resp_dcbab2           == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_dcbab2           == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_rpag?             [%s]\n", p_st_sess->i_ttc8_stmt_resp_rpag             == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_rpag             == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_rpadml?           [%s]\n", p_st_sess->i_ttc8_stmt_resp_rpadml           == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_rpadml           == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oereocs?          [%s]\n", p_st_sess->i_ttc8_stmt_resp_oereocs          == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oereocs          == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oerendseq?        [%s]\n", p_st_sess->i_ttc8_stmt_resp_oerendseq        == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oerendseq        == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oeraij?           [%s]\n", p_st_sess->i_ttc8_stmt_resp_oeraij           == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oeraij           == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oci_oerskip8?     [%s]\n", p_st_sess->i_ttc8_stmt_resp_oci_oerskip8     == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oci_oerskip8     == FR_YES ? "true" : "false");
    printf("* i_ttc8_stmt_resp_oci_oerskip6?     [%s]\n", p_st_sess->i_ttc8_stmt_resp_oci_oerskip6     == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_stmt_resp_oci_oerskip6     == FR_YES ? "true" : "false");
    printf("* i_ttc8_long_analyze_succ?          [%s]\n", p_st_sess->i_ttc8_long_analyze_succ          == APM_ORA_FLAG_UNSET ? KYELLOW "unset" KMAGENTA : p_st_sess->i_ttc8_long_analyze_succ          == FR_YES ? "true" : "false");

    printf("\n* PHASE CONNECT       [%s]\n", APM_ORA_HAS_PHASE_P_CONNECT(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE RESEND        [%s]\n", APM_ORA_HAS_PHASE_P_RESEND(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE RECONNECT     [%s]\n", APM_ORA_HAS_PHASE_P_RECONNECT(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE ACCEPT        [%s]\n", APM_ORA_HAS_PHASE_P_ACCEPT(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE PRO_REQ       [%s]\n", APM_ORA_HAS_PHASE_P_PRO_REQ(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE PRO_RESP      [%s]\n", APM_ORA_HAS_PHASE_P_PRO_RESP(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE DTY_REQ       [%s]\n", APM_ORA_HAS_PHASE_P_DTY_REQ(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE DTY_RESP      [%s]\n", APM_ORA_HAS_PHASE_P_DTY_RESP(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE LOG1_REQ      [%s]\n", APM_ORA_HAS_PHASE_P_LOG1_REQ(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE LOG1_RESP     [%s]\n", APM_ORA_HAS_PHASE_P_LOG1_RESP(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE LOG2_REQ      [%s]\n", APM_ORA_HAS_PHASE_P_LOG2_REQ(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE LOG2_RESP     [%s]\n", APM_ORA_HAS_PHASE_P_LOG2_RESP(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE OVERSION_REQ  [%s]\n", APM_ORA_HAS_PHASE_P_OVERSION_REQ(p_st_sess->ull_bits_phase_progress)?"YES":"NO");
    printf("* PHASE OVERSION_RESP [%s]\n", APM_ORA_HAS_PHASE_P_OVERSION_RESP(p_st_sess->ull_bits_phase_progress)?"YES":"NO");

    printf("*********************************\n");
    printf("*********************************\n" RESET);
}

void __ora_util_print_dty_info(char *p_str, int i_dty)
{
    char arr_str[32] = {'\0'};
    switch (i_dty)
    {
        case ORA_DTY_VARCHAR:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "VARCHAR");
            break;
        case ORA_DTY_NUMBER:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "NUMBER");
            break;
        case ORA_DTY_VARNUM:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "VARNUM");
            break;
        case ORA_DTY_LONG:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "LONG");
            break;
        case ORA_DTY_ROWID2:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "ROWID2");
            break;
        case ORA_DTY_DATE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "DATE");
            break;
        case ORA_DTY_VBI:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "VBI");
            break;
        case ORA_DTY_RAW:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "RAW");
            break;
        case ORA_DTY_LONG_RAW:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "LONG_RAW");
            break;
        case ORA_DTY_ANYTYPE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "ANYTYPE");
            break;
        case ORA_DTY_CHAR:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "CHAR");
            break;
        case ORA_DTY_BINARY_FLOAT:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "BINARY_FLOAT");
            break;
        case ORA_DTY_BINARY_DOUBLE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "BINARY_DOUBLE");
            break;
        case ORA_DTY_RESULT_SET:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "RESULT_SET");
            break;
        case ORA_DTY_ROWID:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "ROWID");
            break;
        case ORA_DTY_NAMED_TYPE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "NAMED_TYPE");
            break;
        case ORA_DTY_REF_TYPE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "REF_TYPE");
            break;
        case ORA_DTY_CLOB:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "CLOB");
            break;
        case ORA_DTY_BLOB:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "BLOB");
            break;
        case ORA_DTY_BFILE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "BFILE");
            break;
        case ORA_DTY_RSET:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "RSET");
            break;
        case ORA_DTY_NAMED_TYPE2:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "NAMED_TYPE2");
            break;
        case ORA_DTY_TIMESTAMP:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "TIMESTAMP");
            break;
        case ORA_DTY_TIMESTAMPTZ:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "TIMESTAMPTZ");
            break;
        case ORA_DTY_INTERVALYM:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "INTERVALYM");
            break;
        case ORA_DTY_INTERVALDS:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "INTERVALDS");
            break;
        case ORA_DTY_UROWID:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "UROWID");
            break;
        case ORA_DTY_TIMESTAMPLTZ:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "TIMESTAMPLTZ");
            break;
        case ORA_DTY_XMLTYPE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "XMLTYPE");
            break;
        case ORA_DTY_DML_RETURN_PARAM:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "DML_RETURN_PARAM");
            break;
        case ORA_DTY_NULL_TYPE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "NULL_TYPE");
            break;
        case ORA_DTY_SET_CHAR_BYTES:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "SET_CHAR_BYTES");
            break;
        case ORA_DTY_T2S_OVERLONG_RAW:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "T2S_OVERLONG_RAW");
            break;
        case ORA_DTY_PLSQL_INDEX_TABLE:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "PLSQL_INDEX_TABLE");
            break;
        case ORA_DTY_FIXED_CHAR:
            snprintf(arr_str, sizeof(arr_str), "%d 0x%02x %s", i_dty, i_dty, "FIXED_CHAR");
            break;
        default:
            snprintf(arr_str, sizeof(arr_str), "%s", "UNKNOWN");
            break;
    }
    printf(p_str, arr_str);
    return;
}

void ora_util_log(unsigned int ui_line, const char *p_func, const char *p_fmt, ...)
{
    FILE *fp;
    va_list st_ap;

    if ((fp = fopen("ora_statistics.log","a")) == NULL)
        return;

    fprintf(fp, "[Line:%u, %s()]\t\t", ui_line, p_func);

    va_start(st_ap, p_fmt);
    vfprintf(fp, p_fmt, st_ap);
    va_end(st_ap);

    fclose(fp);

    return;
}

int ora_util_check_dty(int i_dty)
{
    switch (i_dty)
    {
        case ORA_DTY_VARCHAR:
        case ORA_DTY_NUMBER:
        case ORA_DTY_VARNUM:
        case ORA_DTY_LONG:
        case ORA_DTY_ROWID2:
        case ORA_DTY_DATE:
        case ORA_DTY_VBI:
        case ORA_DTY_RAW:
        case ORA_DTY_LONG_RAW:
        case ORA_DTY_ANYTYPE:
        case ORA_DTY_CHAR:
        case ORA_DTY_BINARY_FLOAT:
        case ORA_DTY_BINARY_DOUBLE:
        case ORA_DTY_RESULT_SET:
        case ORA_DTY_ROWID:
        case ORA_DTY_NAMED_TYPE:
        case ORA_DTY_REF_TYPE:
        case ORA_DTY_CLOB:
        case ORA_DTY_BLOB:
        case ORA_DTY_BFILE:
        case ORA_DTY_RSET:
        case ORA_DTY_NAMED_TYPE2:
        case ORA_DTY_TIMESTAMP:
        case ORA_DTY_TIMESTAMPTZ:
        case ORA_DTY_INTERVALYM:
        case ORA_DTY_INTERVALDS:
        case ORA_DTY_UROWID:
        case ORA_DTY_TIMESTAMPLTZ:
        case ORA_DTY_XMLTYPE:
        case ORA_DTY_DML_RETURN_PARAM:
        case ORA_DTY_NULL_TYPE:
        case ORA_DTY_SET_CHAR_BYTES:
        case ORA_DTY_T2S_OVERLONG_RAW:
        case ORA_DTY_PLSQL_INDEX_TABLE:
        case ORA_DTY_FIXED_CHAR:
            return FR_SUCC;
        default:
            return FR_FAIL;
    }
    return FR_FAIL;
}

int ora_util_check_charset(int i_charset)
{
    switch (i_charset)
    {
        case -1:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 25:
        case 27:
        case 28:
        case 31:
        case 32:
        case 33:
        case 34:
        case 35:
        case 36:
        case 37:
        case 38:
        case 39:
        case 40:
        case 41:
        case 42:
        case 43:
        case 44:
        case 45:
        case 46:
        case 47:
        case 48:
        case 49:
        case 50:
        case 51:
        case 52:
        case 61:
        case 70:
        case 72:
        case 81:
        case 82:
        case 90:
        case 91:
        case 92:
        case 93:
        case 94:
        case 95:
        case 96:
        case 97:
        case 98:
        case 99:
        case 100:
        case 101:
        case 110:
        case 113:
        case 114:
        case 140:
        case 150:
        case 152:
        case 153:
        case 154:
        case 155:
        case 156:
        case 158:
        case 159:
        case 160:
        case 161:
        case 162:
        case 163:
        case 164:
        case 165:
        case 166:
        case 167:
        case 170:
        case 171:
        case 172:
        case 173:
        case 174:
        case 175:
        case 176:
        case 177:
        case 178:
        case 179:
        case 180:
        case 181:
        case 182:
        case 183:
        case 184:
        case 185:
        case 186:
        case 187:
        case 188:
        case 189:
        case 190:
        case 191:
        case 192:
        case 193:
        case 194:
        case 195:
        case 196:
        case 197:
        case 198:
        case 199:
        case 200:
        case 201:
        case 202:
        case 203:
        case 204:
        case 205:
        case 206:
        case 207:
        case 208:
        case 210:
        case 211:
        case 221:
        case 222:
        case 223:
        case 224:
        case 225:
        case 226:
        case 230:
        case 231:
        case 232:
        case 233:
        case 235:
        case 239:
        case 241:
        case 251:
        case 261:
        case 262:
        case 263:
        case 264:
        case 265:
        case 266:
        case 267:
        case 277:
        case 278:
        case 279:
        case 301:
        case 311:
        case 312:
        case 314:
        case 315:
        case 316:
        case 317:
        case 319:
        case 320:
        case 322:
        case 323:
        case 324:
        case 325:
        case 326:
        case 327:
        case 351:
        case 352:
        case 353:
        case 354:
        case 368:
        case 380:
        case 381:
        case 382:
        case 383:
        case 384:
        case 385:
        case 386:
        case 390:
        case 401:
        case 500:
        case 504:
        case 505:
        case 506:
        case 507:
        case 508:
        case 509:
        case 511:
        case 514:
        case 554:
        case 555:
        case 556:
        case 557:
        case 558:
        case 559:
        case 560:
        case 561:
        case 563:
        case 565:
        case 566:
        case 567:
        case 590:
        case 797:
        case 798:
        case 829:
        case 830:
        case 831:
        case 832:
        case 833:
        case 834:
        case 835:
        case 836:
        case 837:
        case 838:
        case 840:
        case 842:
        case 845:
        case 846:
        case 850:
        case 851:
        case 852:
        case 853:
        case 854:
        case 860:
        case 861:
        case 862:
        case 863:
        case 864:
        case 865:
        case 866:
        case 867:
        case 868:
        case 870:
        case 871:
        case 872:
        case 873:
        case 992:
        case 996:
        case 997:
        case 998:
        case 1001:
        case 2000:
        case 2002:
            return FR_SUCC;
        default:
            return FR_FAIL;
    }
    return FR_FAIL;
}


/*******************************************************************************
*  FUNC     :  从 ORA-01403: 未找到任何数据 中提取 ORA-01403
*  ARGS     :  *p_error_mesg                (ORA-01403: 未找到任何数据)
*           :  **pp_code_string             (ORA-01403)
*  RTN      :  0                            (FR_SUCC)
*              1                            (FR_FAIL)
*  NOTE     :  需要外部释放*p_code_string的内存
*******************************************************************************/
void ora_util_extract_code_string(char *p_error_mesg
                                , char **pp_code_string)
{
    char *p_pos_colon = NULL;
    char *p_code_string = NULL;
    int i_code_string_len = 0;

    if (strlen(p_error_mesg) == 0 || (p_pos_colon = strchr(p_error_mesg, ':')) == NULL)
        return;

    i_code_string_len = (int) (p_pos_colon - p_error_mesg);

    if ((p_code_string = (char *) frmemdup(p_error_mesg, (size_t) (i_code_string_len + 1))) == NULL)
        return;

    p_code_string[i_code_string_len] = '\0';
    *pp_code_string = p_code_string;

    return;
}

/*******************************************************************************
*  FUNC     :  检查返回的错误码是否符合规范
*  ARGS     :  *p_error_mesg                (ORA-01403: 未找到任何数据)
*           :  **pp_code_string             (ORA-01403)
*  RTN      :  0                            (FR_SUCC)
*              1                            (FR_FAIL)
*  NOTE     :  需要外部释放*p_code_string的内存
*******************************************************************************/
int ora_check_error_mesg(const char *p_error_mesg)
{
    ORA_PRINT_INFO("ora_check_error_mesg...\n");
    if (p_error_mesg == NULL)
        return FR_FAIL;

    if (strncasecmp(p_error_mesg, "ORA-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NZE-", 4) == 0 ||
        strncasecmp(p_error_mesg, "EXP-", 4) == 0 ||
        strncasecmp(p_error_mesg, "IMP-", 4) == 0 ||
        strncasecmp(p_error_mesg, "SQL*", 4) == 0 ||
        strncasecmp(p_error_mesg, "KUP-", 4) == 0 ||
        strncasecmp(p_error_mesg, "UDE-", 4) == 0 ||
        strncasecmp(p_error_mesg, "UDI-", 4) == 0 ||
        strncasecmp(p_error_mesg, "DBV-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NID-", 4) == 0 ||
        strncasecmp(p_error_mesg, "DGM-", 4) == 0 ||
        strncasecmp(p_error_mesg, "DIA-", 4) == 0 ||
        strncasecmp(p_error_mesg, "LCD-", 4) == 0 ||
        strncasecmp(p_error_mesg, "OCI-", 4) == 0 ||
        strncasecmp(p_error_mesg, "RMAN-", 5) == 0 ||
        strncasecmp(p_error_mesg, "LRM-", 4) == 0 ||
        strncasecmp(p_error_mesg, "LFI-", 4) == 0 ||
        strncasecmp(p_error_mesg, "PLS-", 4) == 0 ||
        strncasecmp(p_error_mesg, "AMD-", 4) == 0 ||
        strncasecmp(p_error_mesg, "CLSR-", 5) == 0 ||
        strncasecmp(p_error_mesg, "CLSS-", 5) == 0 ||
        strncasecmp(p_error_mesg, "CRS-", 4) == 0 ||
        strncasecmp(p_error_mesg, "EVM-", 4) == 0 ||
        strncasecmp(p_error_mesg, "CLST-", 5) == 0 ||
        strncasecmp(p_error_mesg, "CLSD-", 5) == 0 ||
        strncasecmp(p_error_mesg, "PROC-", 5) == 0 ||
        strncasecmp(p_error_mesg, "PROT-", 5) == 0 ||
        strncasecmp(p_error_mesg, "TNS-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NNC-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NNO-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NNL-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NPL-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NNF-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NMP-", 4) == 0 ||
        strncasecmp(p_error_mesg, "NCR-", 4) == 0 ||
        strncasecmp(p_error_mesg, "O2F-", 4) == 0 ||
        strncasecmp(p_error_mesg, "O2I-", 4) == 0 ||
        strncasecmp(p_error_mesg, "O2U-", 4) == 0 ||
        strncasecmp(p_error_mesg, "PCB-", 4) == 0 ||
        strncasecmp(p_error_mesg, "PCC-", 4) == 0 ||
        strncasecmp(p_error_mesg, "SQL-", 4) == 0 ||
        strncasecmp(p_error_mesg, "AUD-", 4) == 0 ||
        strncasecmp(p_error_mesg, "IMG-", 4) == 0 ||
        strncasecmp(p_error_mesg, "VID-", 4) == 0 ||
        strncasecmp(p_error_mesg, "DRG-", 4) == 0 ||
        strncasecmp(p_error_mesg, "LPX-", 4) == 0 ||
        strncasecmp(p_error_mesg, "LSX-", 4) == 0 ||
        strncasecmp(p_error_mesg, "PGA-", 4) == 0 ||
        strncasecmp(p_error_mesg, "PGU-", 4) == 0)
        return FR_SUCC;
    return FR_FAIL;
}
